import json

import requests
import win32api
import win32con
import Page
import allure
from time import sleep
from numpy import random
from Base.base import Base
from Base.base_data import Setting as a
from Base.get_driver import get_driver
from Base.telnet_client import TelnetClient
from selenium.webdriver.common.by import By

"""PageDevices类，作为设备列表页,继承Base类"""


class PageDevice(Base):

    # ---------------------------------------[单个操作]依赖/组合业务/断言使用------------------------------------------------

    @allure.step(title="点击 添加设备空间")
    def page_click_create_space_btn(self):
        self.index_click_element(Page.space_create_btns, 1)  # 第一个应用

    @allure.step(title="输入 设备空间名")
    def page_enter_space_name(self, space_name):
        self.send_element(Page.space_name_input, space_name)

    @allure.step(title="点击 修改设备空间")
    def page_click_edit_space_btn(self, space_name):
        sleep(1)
        if len(space_name) > 20:  # 通过space_name
            space_name = space_name[:20]
        xpath = "// *[contains(text(), '{}')] /../span/span[1]/img".format(space_name)
        self.search_element((By.XPATH, xpath), timeout=5).click()

    @allure.step(title="点击 删除设备空间")
    def page_click_del_space_btn(self, space_name):
        if len(space_name) > 20:  # 通过space_name
            space_name = space_name[:20]
        toast_xpath = "// *[contains(text(), '{}')] /../span/span[2]/img" \
            .format(space_name)
        return self.search_element((By.XPATH, toast_xpath), timeout=5).click()

    @allure.step(title="点击 移动到")
    def page_click_move_space_btn(self):
        self.click_element(Page.dev_move_space_btn)

    @allure.step(title="点击 调参")
    def page_click_param_btn(self):
        self.click_element(Page.dev_param_btn)

    @allure.step(title="点击 升级")
    def page_click_upgrade_btn(self):
        sleep(1)
        self.click_element(Page.dev_upgrade_btn)

    @allure.step(title="点击 移除")
    def page_click_remove_btn(self):
        self.click_element(Page.dev_remove_btn)

    @allure.step(title="点击 设置")
    def page_click_device_config(self, device_ip, device_type):
        if device_type == "客流识别机":  # 通过device_ip
            path = "//td[contains(text(),'{}')]/../td[12]/div/span[1]" \
                .format(device_ip)
            self.search_element((By.XPATH, path), timeout=5).click()
        else:
            path = "//td[contains(text(),'{}')]/../td[11]/div/div/span" \
                .format(device_ip)
            self.search_element((By.XPATH, path), timeout=5).click()
        sleep(1)

    @allure.step(title="点击 重启")
    def page_click_device_reboot(self, device_ip, device_type):
        if device_type == "客流识别机":
            path = "//td[contains(text(),'{}')]/../td[12]/div/span[2]" \
                .format(device_ip)
            self.search_element((By.XPATH, path), timeout=5).click()
        else:
            path = "//td[contains(text(),'{}')]/../td[11]/div/span" \
                .format(device_ip)
            self.search_element((By.XPATH, path), timeout=5).click()

    @allure.step(title="点击 编辑ipc位置")
    def page_click_device_edit_position(self, device_ip, device_type):
        if device_type == "客流识别机":
            path = "//td[contains(text(),'{}')]/../td[8]/span/span/i".format(device_ip)  # 通过device_ip
            self.search_element((By.XPATH, path), timeout=5).click()
        else:
            path = "//td[contains(text(),'{}')]/../td[7]/span/span/i".format(device_ip)  # 通过device_ip
            self.search_element((By.XPATH, path), timeout=5).click()

    @allure.step(title="空间栏搜索框 -->输入搜索值")
    def page_click_space_search_input(self, search_text):
        self.send_element(Page.space_search_input, search_text)
        sleep(2)
        # 调用 敲键盘的回车键
        self.knock_enter_key(Page.space_search_input)

    @allure.step(title="设备搜索框 -->输入搜索值")
    def page_click_device_search_input(self, search_text):
        self.send_element(Page.dev_search_input, search_text)
        sleep(2)
        # 点击搜索放大镜
        self.click_element(Page.dev_search_btn)

    @allure.step(title="移动设备 -->点击下拉框")
    def page_click_space_select(self):
        sleep(2)
        self.click_element(Page.dev_space_select)

    @allure.step(title="移动设备 -->选择空间选项")
    def page_sel_option(self):
        # if move_space_name == "Guo_Flow":
        self.click_element(Page.com_option_second)
        # sleep(1)
        # if move_space_name == "Guo_Snap":
        #     self.click_element(Page.com_option_third)
        # sleep(1)
        # if move_space_name == "Guo_Recog":
        #     self.click_element(Page.com_option_four)
        # sleep(1)

    # 选择唯一个下拉框的值---【调参操作依赖】
    def page_first_sel_opt(self, index):
        allure.attach("描述", "选择第{}个选项".format(index))
        xpath = (By.XPATH, "//li[contains(text(), '{}')]".format(index))
        self.search_element(xpath).click()

    # 选择非唯一下拉框的值---【调参操作依赖】
    def page_sel_opt(self, i, index):
        allure.attach("描述", "选择第{}个下拉框，第{}个选项".format(i, index))
        xpath = (By.XPATH, "//li[contains(text(), '{}')]".format(index))
        self.index_click_element(xpath, i)

    @allure.step(title="抓拍参数 -->灵敏度")
    def page_set_track(self, opt_track):
        if type(opt_track) == int:
            # 点击灵敏度下拉框
            self.click_element(Page.prarm_track_score_eliminate)
            # 调用 选择下拉选项  opt_track = int (1-10)
            self.page_first_sel_opt(opt_track)  # 灵敏度为第1个下拉框
            sleep(2)

    @allure.step(title="抓拍参数 -->目标抓拍时间")
    def page_set_begin(self, opt_begin):
        if (type(opt_begin) == int) and (opt_begin != 5):
            # 点击目标抓拍时间下拉框
            self.click_element(Page.prarm_beginpostframethr)
            # 调用 选择下拉选项  opt_begin = int (1-10)
            self.page_sel_opt(3, opt_begin)  # 目标抓拍时间为第3个下拉框
            sleep(2)

    @allure.step(title="抓拍参数 -->抓拍阈值")
    def page_set_fro(self, opt_fro):
        if type(opt_fro) == int:
            # 点击抓拍阈值下拉框
            self.click_element(Page.prarm_frontthr)
            # 调用 选择下拉选项  opt_fro = int (1-10)
            self.page_sel_opt(2, opt_fro)  # 抓拍阈值为第2个下拉框
            sleep(2)

    @allure.step(title="抓拍参数 -->是否重复抓拍")
    def page_set_recapture(self, re_radio, opt_re):
        # 开启重复抓拍
        if re_radio == 1:
            # 重复抓拍未开启时
            if int(self.search_element(Page.prarm_if_re_in)
                           .get_attribute("value")) != 1:
                # 开启重复抓拍
                self.click_element(Page.prarm_if_re_off)
                allure.attach("描述", "开启重复抓拍")
            allure.attach("描述", "抓拍参数 -->再次抓取时间差")
            self.click_element(Page.prarm_resnapthr)
            self.page_sel_opt(4, opt_re)  # 再次抓取时间差为第4个下拉框
            sleep(2)
        # 关闭重复抓拍
        elif re_radio == 0:
            # 重复抓拍开启时
            if int(self.search_element(Page.prarm_if_re_in)
                           .get_attribute("value")) != 2:
                # 关闭重复抓拍
                self.click_element(Page.prarm_if_re_off)
                allure.attach("描述", "重复抓拍已开启")
        sleep(2)

    @allure.step(title="抓拍参数 -->抓拍图片数")
    def page_set_images(self, img_num):
        if type(img_num) == int and img_num < 4:
            # 调用 输入文本2  img_num = int (1-3)
            self.parm_send_element(Page.prarm_firstnumavailthr, img_num)

    @allure.step(title="抓拍参数 -->人脸外廓系数")
    def page_set_snapscale(self, sna_num):
        if type(sna_num) == str:
            # 调用 输入文本2 sna_num = str(1.0-4.0)
            self.parm_send_element(Page.prarm_snapscale, sna_num)

    @allure.step(title="抓拍参数 -->抓拍最小人脸尺寸")
    def page_set_snapsizethr(self, size_num):
        if type(size_num) == int:
            # 调用 输入文本2 size_num =int(32-256) 识别机最小参数为64
            self.parm_send_element(Page.prarm_snapsizethr, size_num)

    @allure.step(title="升级设备 -->点击下拉框")
    def page_click_version_select(self):
        sleep(2)
        self.click_element(Page.dev_version_select)

    @allure.step(title="升级设备 -->选择版本选项")
    def page_sel_version_option(self, ota_version):
        sleep(2)
        if ota_version == "first":
            self.click_element(Page.com_option_first)
        if ota_version == "second":
            self.click_element(Page.com_option_second)
        sleep(2)

    # 获取第一个应用下所有设备空间名
    def page_get_space_names(self):
        return self.search_elements(Page.space_names)

    # 获取所有应用名
    def page_get_app_names(self):
        return self.search_elements(Page.space_app_names)

    # @allure.step(title="点击 设备前的复选框")
    def page_click_ip_checkbox(self, device_ip):
        try:
            sleep(1)
            if device_ip != "":
                xpath = \
                    "//td[contains(text(),'{}')]/../td[1]/span/label/span/input" \
                        .format(device_ip)
                self.search_element((By.XPATH, xpath), timeout=5).click()
        except Exception:
            pass

    # 通过device_ip -->返回设备ota版本值
    def page_get_device_ota(self, device_ip, device_type):
        a = 8
        if device_type == "客流识别机":
            a = 9
        path = "//td[contains(text(),'{}')]/../td[{}]/span" \
            .format(device_ip, a)
        return self.search_element((By.XPATH, path), timeout=5).text

    # 通过device_ip -->返回设备状态值
    def page_get_device_status(self, device_ip, device_type):
        sleep(2)
        a = 10
        if device_type == "客流识别机":
            a = 11
        toast_xpath = "//td[contains(text(),'{}')]/../td[{}]/div/div/span" \
            .format(device_ip, a)
        return self.search_element((By.XPATH, toast_xpath), timeout=5).text

    # 通过device_ip -->点击设备状态详细信息
    def page_click_device_status(self, device_ip, device_type):
        a = 10
        if device_type == "客流识别机":
            a = 10 + 1
        path = "//td[contains(text(),'{}')]/../td[{}]/div/div/span" \
            .format(device_ip, a)
        self.search_element((By.XPATH, path), timeout=5).click()

    # 通过device_ip -->返回设备位置信息值
    def page_get_device_position(self, device_ip, device_type):
        if device_type == "客流识别机":
            path = "//td[contains(text(),'{}')]/../td[8]/span/span".format(device_ip)
            return self.search_element((By.XPATH, path), timeout=5).text
        else:
            path = "//td[contains(text(),'{}')]/../td[7]/span/span".format(device_ip)
            return self.search_element((By.XPATH, path), timeout=5).text

    # 通过device_ip -->返回设备在线状态值
    def page_get_device_online_status(self, device_ip):
        path = "//td[contains(text(),'{}')]/../td[5]/div/span[2]" \
            .format(device_ip)
        return self.search_element((By.XPATH, path), timeout=5).text

    # 通过device_ip -->返回设备SN号值
    def page_get_device_sn(self, device_ip):
        path = "//td[contains(text(),'{}')]/..".format(device_ip)
        ele = self.search_element((By.XPATH, path))
        return ele.get_attribute("data-row-key")

    @allure.step(title="返回设备是否画线值")
    def get_device_if_line(self, device_ip):
        path = "//td[contains(text(),'{}')]/../td[7]/span".format(device_ip)
        ele = self.get_text((By.XPATH, path))
        return ele

    @allure.step(title="返回设备是否画域值")
    def get_device_if_area(self, device_ip):
        path = "//td[contains(text(),'{}')]/../td[6]/span".format(device_ip)
        ele = self.get_text((By.XPATH, path))
        return ele

    @allure.step(title="点击 设备机型下拉框")
    def page_click_device_type_select(self):
        sleep(2)
        self.click_element(Page.dev_type_select)

    @allure.step(title="更改IPC位置 -->输入位置信息")
    def page_enter_position(self, position_text):
        self.send_element(Page.dev_edit_position_input, position_text)

    @allure.step(title="设置页面 -->输入阈值")
    def page_enter_threshold_input(self, threshold, tag):
        # 调用 键盘清空 -->输入文本
        self.parm_send_element(Page.dev_first_threshold_input, threshold)
        if tag == 2:
            # 调用 键盘清空 -->输入文本
            self.parm_send_element(Page.dev_second_threshold_input, threshold)
        sleep(1)

    @allure.step(title="设置页面 -->点击保存")
    def page_config_click_save(self):
        sleep(1)
        self.click_element(Page.dev_config_save_btn)

    @allure.step(title="设置页面 -->点击取消")
    def page_config_click_canal(self):
        sleep(1)
        self.click_element(Page.dev_config_canal_btn)

    @allure.step(title="判断取消按钮是否在页面")
    def if_cancel_exist(self):
        sleep(5)
        cancel = self.base_element_is_exist(Page.dev_config_canal_btn)
        return cancel

    @allure.step(title="设置页面 -->点击识别开关")
    def page_open_recog(self):
        # 获取识别开关文本，如果是off，则点击打开
        if self.get_text(Page.dev_config_open_recog) == "OFF":
            # 点击识别开关
            sleep(1)
            self.click_element(Page.dev_config_recog_btn)
        sleep(1)

    @allure.step(title="点击 图片刷新")
    def click_img_refresh_btn(self):
        try:
            sleep(2)
            self.click_element(Page.dev_img_refresh_btn)
        except Exception:
            return False

    @allure.step(title="设置页面 -->点击绘制线")
    def click_draw_lines_radio(self, index):  # 0为进出线，1为途经线
        self.index_click_element(Page.dev_config_lines_btn, index)

    @allure.step(title="设置页面 -->点击删除线")
    def click_del_line_btn(self):
        self.click_element(Page.dev_del_line_btns)

    @allure.step(title="设置页面 -->点击删除域")
    def click_del_area_btn(self):
        self.click_element(Page.dev_del_area_btn)

    @allure.step(title="设置页面 -->点击开启区域抓拍")
    def click_enable_area(self):
        self.click_element(Page.dev_enable_box)

    @allure.step(title="设置页面 -->画域线")
    def draw_area_line(self):
        sleep(3)
        win32api.SetCursorPos((600, 600))
        win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 600, 600, 0, 0)
        sleep(2)
        win32api.SetCursorPos((900, 900))
        sleep(2)
        win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 900, 900, 0, 0)

    @allure.step(title="删除设备空间 -->点击知道了")
    def page_click_know(self):
        sleep(1)
        self.click_element(Page.com_know_btn)

    # ---------------------------------------------------[依赖]组合业务/断言使用---------------------------------------------

    # 依赖 -->判断设备空间是否有0台【清理空间操作依赖】True/False
    def page_space_empty(self):
        # 获取所有设备空间统计台数元素
        ipc_num = self.search_elements(Page.space_ipc_nums)
        # 判断是否有0台
        num = 0
        for i in range(1, len(ipc_num)):
            if ipc_num[i].text != "0台":
                num += 1
        if num == len(ipc_num) - 1:
            return True
        else:
            return False

    # 依赖 -->获取设备空间栏所有app_name+space_name【空间搜索框断言依赖】返回list
    def page_get_names(self):
        try:
            names = []
            # 调用 获取第一个应用下所有设备空间名
            names_ele = self.page_get_space_names()
            for i in names_ele:
                names.append(i.text)
            # 调用 获取所有应用名
            names_ele = self.page_get_app_names()
            for i in names_ele:
                names.append(i.text)
            allure.attach("描述", "空间栏所有name:[{}]".format(names))
            allure.attach("描述", "空间栏所有name_num：[{}]".format(len(names)))
            return names
        except Exception as e:
            allure.attach("失败描述", "获取name失败,原因:[{}]".format(e))
            # 截图
            self.screen_page()
            return False

    # 依赖 -->获取页面所有参数【调参断言依赖】返回list
    def page_get_page_prarms(self, device_ip):
        try:
            # 调用 点击调参按钮
            self.page_click_param_btn()
            page_param = []
            # 灵敏度
            track = self.get_text(Page.prarm_track_score_eliminate)
            page_param.append(track)
            # 目标抓拍时间
            begin = self.get_text(Page.prarm_beginpostframethr)
            page_param.append(begin)
            # 抓拍图片数
            fir = self.search_element(Page.prarm_firstnumavailthr).get_attribute("value")
            page_param.append(fir)
            # 抓拍阈值
            fro = self.get_text(Page.prarm_frontthr)
            page_param.append(fro)
            # 人脸外廓系数
            sna0 = self.search_element(Page.prarm_snapscale).get_attribute("value")
            page_param.append(sna0)
            # 抓拍最小人脸尺寸
            size = self.search_element(Page.prarm_snapsizethr).get_attribute("value")
            page_param.append(size)
            # 再次抓取时间差
            if int(self.search_element(Page.prarm_if_re_in).get_attribute("value")) == 1:
                re = self.get_text(Page.prarm_resnapthr)
                page_param.append(re)
            allure.attach("描述", "页面参数：灵/目标/图片/阈值/人脸尺寸/系数/时间差:[{}]"
                          .format(page_param))
            return page_param
        except Exception as e:
            allure.attach("失败描述", "页面取出所有参数失败，原因：[{}]".format(e))
            assert False
        finally:
            # 关闭调参页面
            self.close_message_box()

    # 依赖 -->转换配置所有参数【调参断言依赖】返回list
    def page_trans_set_params(self,
                              opt_fro, opt_track, opt_begin, opt_re,
                              img_num, sna_num, size_num, re_radio):
        """
        :param opt_track: 灵敏度(1-10)
        :param opt_begin: 目标抓拍时间(1-10)
        :param opt_re: 再次抓取时间差(1-10) 客流机无此参数给None
        :param img_num: 抓拍图片数(1-3) 客流机与识别机无此参数给5
        :param sna_num: 人脸外廓系数(1.0-4.0)
        :param size_num: 抓拍最小人脸尺寸(32-256) 识别机最小参数为64
        :param re_radio:  是否开启重复抓拍：0为关闭，1为开启 客流机无此参数
        :param opt_fro: 抓拍阈值(21-30)
        :return:
        """
        # 灵敏度
        param = [opt_track]
        # 目标抓拍时间
        if opt_begin != None:
            # 客流识别不可调，默认为5
            param.append(opt_begin)
        # 抓拍图片数
        if img_num == None or img_num == 5:
            param.append(1)
        else:
            param.append(img_num)
        # 抓拍阈值
        param.append(opt_fro)
        # 最小人脸尺寸
        param.append(sna_num)
        # 人脸外扩系数
        param.append(size_num)
        # 再次抓取时间差1
        if re_radio == 0:
            param.append(None)
        else:
            param.append(opt_re)
        # 返回所有参数param列表
        allure.attach("描述", "转配置参数：灵/目标/图片/阈值/人脸尺寸/系数/时间差:[{}]"
                      .format(param))
        return param

    # 依赖 -->获取页面space_id【移动/移除IPC断言/接入设备操作依赖】返回str
    def page_get_move_page_space_id(self):
        try:
            # 调用 通过文本点击元素 -->点击设备空间tab
            self.text_click_element(a.space_name)
            # 调用 获取元素文本值 -->返回页面space_id值
            page_space_id = self.get_text(Page.dev_list)[7:]
            allure.attach("描述", "页面取出space_id为:[{}]".format(page_space_id))
            return page_space_id
        except Exception:
            allure.attach("失败描述", "获取页面space_id失败")
            return None

    # 依赖 -->返回设备空间栏指定name的数量  【搜索/筛选断言依赖】返回int
    @allure.step(title="返回设备空间栏指定name的数量")
    def page_get_result_name_num(self, search_text):
        try:
            sleep(2)
            # 调用 获取设备空间栏所有app_name+space_name
            all_name = self.page_get_names()
            name = []
            # 取出符合搜索内容search_text的值
            for i in all_name:
                if (search_text in i) or (search_text == i):
                    name.append(i)
            return len(name)
        except:
            allure.attach("错误说明", "返回search_text：[{}]的数量操作失败"
                          .format(search_text))
            return None

    # 依赖 -->获取页面设备信息  【设备搜索/筛选断言依赖】返回list
    @allure.step(title="获取页面设备信息")
    def page_get_device_text(self, search_text):
        try:
            sleep(2)
            # 调用 通过文本定位一组元素 -->返回搜索内容所有元素
            all_text_ele = self.text_search_elements(search_text)
            text_num = len(all_text_ele)
            all_text = []
            for i in range(0, text_num):
                if (all_text_ele[i].text == "") or (len(all_text_ele[i].text) == 14):
                    pass
                else:
                    all_text.append(all_text_ele[i].text)
            allure.attach("描述", "设备列表所有指定信息文本:[{}]".format(all_text))
            allure.attach("描述", "设备列表所有指定信息数量:[{}]".format(len(all_text)))
            return all_text, len(all_text)
        except Exception as e:
            allure.attach("错误说明", "获取页面设备信息操作失败,原因：[{}]".format(e))
            # 截图
            self.screen_page()
            return 0

    # 依赖 -->查询人脸库阈值【断言页面阈值 == 查询阈值使用】返回threshold
    def api_search_faces(self, faceset_id, device_ip):
        try:
            data = json.dumps({"libid": faceset_id})
            data = bytes(data, 'utf-8')  # 格式化请求体
            url = "http://" + device_ip + ":8089/api/v1/recognize/get_fdlib"  # 请求url
            res = requests.post \
                (url=url, headers={'Content-Type': 'application/json'},
                 data=data)  # 发送请求
            allure.attach('描述', '响应状态码:{}'.format(res.status_code))
            allure.attach('描述', '响应信息:{}'.format(res.text))
            # 返回人脸库阈值
            return res.json().get("data").get("threshold")
        except Exception as e:
            allure.attach("错误说明", "查询人脸库操作失败,原因:[{}]".format(e))
            raise Exception("失败从接口取到人脸库阈值")

    # 依赖 -->设置页面,获取两个人脸库阈值
    @allure.step("设置页面,获取两个脸库阈值")
    def page_get_threshold_input(self, device_ip, device_type):
        # 调用 点击设置按钮
        self.page_click_device_config(device_ip, device_type)
        thresholds = []
        # 清除线
        self.clear_line()
        thresholds.append(int(self.search_element(Page.dev_first_threshold_input).get_attribute("value")))
        thresholds.append(int(self.search_element(Page.dev_second_threshold_input).get_attribute("value")))
        allure.attach("描述", "页面两个人脸库阈值：[{}]".format(thresholds))
        # 调用 点击取消按钮
        self.page_config_click_canal()
        return thresholds

    # # 依赖 -->接口获取两个人脸库阈值
    # @allure.step("接口获取两个脸库阈值")
    # def page_get_two_faceset_text(self, device_ip):
    #     api_thresholds = []
    #     api_thresholds.append(self.api_search_faces(Page.faceset_id_01, device_ip))
    #     api_thresholds.append(self.api_search_faces(Page.faceset_id_02, device_ip))
    #     allure.attach("描述", "api两个人脸库阈值：[{}]".format(api_thresholds))
    #     return api_thresholds

    # 依赖 -->输入阈值  device_type为设备机型 客流识别机/识别机 调阈值使用
    def config_threshold_ipc(self, threshold, tag):
        try:
            # 调用 设置页面 -->输入阈值 tag=2时，分别在两个输入框输入阈值threshold
            self.page_enter_threshold_input(threshold, tag)
            # 调用 设置页面 -->点击保存按钮
            self.page_config_click_save()
        except Exception as e:
            allure.attach("错误说明", "调阈值操作失败,原因:[{}]".format(e))
            # 截图
            self.screen_page()
            raise Exception("调阈值操作失败")

    # 依赖 -->创建一个人脸库【单独使用，需要人脸库时调用创建】更新Page下__init__中faceset_id
    def api_create_faces(self):
        try:
            body = {"name": "guo_auto_{}".format(random.randint(0, 100))}
            # 调用 发送POST请
            r = self.http_post("/openapi/v1/facesets", "POST", body)
            # 返回的faceset_id
            return r.json().get("data").get("faceset_id")
        except Exception as e:
            allure.attach("错误说明", "创建人脸库操作失败,原因:[{}]".format(e))
            raise Exception("失败从接口创建一个人脸库")

    # 依赖 -->绑定人脸库【单独使用，需要绑定人脸库时调用】其他所有代码不使用
    def api_bind_faces(self, device_sn, faceset_id):
        try:
            # 调用 发送POST请
            path = "/openapi/v1/facesets/{}/bind".format(faceset_id)
            body = {"device_list": [{"device_sn": device_sn, "threshold": "0.88"}]}
            r = self.http_post(path, 'POST', body)
            # 调用 断言 -->keyword in expect结果
            assert self.base_if_include("200000", r.json().get("code"))
            return faceset_id
        except Exception as e:
            allure.attach("错误说明", "绑定人脸库操作失败,原因:[{}]".format(e))
            raise Exception("失败从接口将人脸库绑到设备上[{}]".format(device_sn))

    # 依赖 -->为设备添加人脸库 【调阈值操作前置】
    # def add_ipc_faceset(self, device_ip, device_type, tag):
    # # 调用 通过device_ip -->返回设备SN号值
    # device_sn = self.page_get_device_sn(device_ip)
    # # 调用 通过device_ip -->点击设置按钮
    # self.page_click_device_config(device_ip, device_type)
    # # 调用 判断阈值输入框有几个
    # i = self.if_threshold_num()
    # faceset_ids = []
    # while i < tag:
    #     # 调用 依赖 -->绑定人脸库
    #     faceset_ids.append(self.api_bind_faces(device_sn))
    #     i += 1
    # # 接口绑定人脸库后，有延迟
    # sleep(15)
    # return faceset_ids

    # 依赖 -->判断阈值输入框数量【添加设备人脸库使用】
    # def if_threshold_num(self):
    #     # 定位阈值输入框
    #     if not self.base_element_is_exist(Page.dev_first_threshold_input):
    #         return 0
    #     elif not self.base_element_is_exist(Page.dev_first_threshold_input):
    #         return 1
    #     else:
    #         return 2

    # ---------------------------------------------------[组合业务]test脚本使用----------------------------------------------

    # 组合业务方法  -->添加设备空间业务直接调用
    @allure.step(title="添加设备空间操作")
    def add_device_space(self, space_name):
        try:
            # 调用 点击添加设备空间按钮
            self.page_click_create_space_btn()
            # 调用 输入设备空间名
            self.page_enter_space_name(space_name)
            # 调用 点击确定
            self.page_click_com_accept()
        except Exception as e:
            allure.attach("失败描述", "添加设备空间失败，原因：[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("添加设备空间失败")
            return False

    # 组合业务方法  -->修改设备空间业务直接调用
    @allure.step(title="修改设备空间名操作")
    def edit_device_space(self, space_name, new_space_name):
        try:
            # 调用 点击修改设备空间按钮
            self.page_click_edit_space_btn(space_name)
            # 调用 输入空间名
            self.page_enter_space_name(new_space_name)
            # 调用 点击确定
            self.page_click_com_accept()
        except Exception as e:
            allure.attach("失败描述", "修改设备空间失败，原因：[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            raise Exception("修改设备空间失败")

    # 组合业务方法  -->删除设备空间业务直接调用
    @allure.step(title="删除设备空间操作")
    def del_device_space(self, space_name):
        try:
            # 调用 点击删除设备空间按钮
            self.page_click_del_space_btn(space_name)
            # 点击确定
            self.page_click_com_accept()
        except Exception as e:
            allure.attach("失败描述", "修改设备空间失败，原因：[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            raise Exception("删除设备空间失败")

    # 组合业务方法  -->移动ipc业务直接调用
    @allure.step(title="移动ipc到指定设备空间操作")
    def move_ipc(self):
        try:
            # 调用 点击移动到按钮
            self.page_click_move_space_btn()
            # 调用 点击设备空间下拉框
            self.page_click_space_select()
            # 调用 选择下拉框选项 ("Guo_Flow"/"Guo_Snap"/"Guo_Recog")
            self.page_sel_option()
            # 调用 点击确定
            self.page_click_accept()
        except Exception as e:
            allure.attach("失败描述", "移动ipc到指定设备空间失败，原因：[{}]".format(e))
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("移动ipc到指定设备空间失败")
            return False

    # 组合业务方法  -->IPC调参业务直接调用
    @allure.step(title="IPC调参操作")
    def param_ipc(self,
                  opt_track, opt_begin, opt_fro,
                  opt_re, img_num, sna_num, size_num, re_radio):
        try:
            # 调用 点击调参按钮
            self.page_click_param_btn()
            # 调用 设置灵敏度参数 opt_track = int(1-10)  第一个下拉框
            self.page_set_track(opt_track)
            # 调用 设置抓拍阈值参数 opt_fro = int (1-10)  第二个下拉框
            self.page_set_fro(opt_fro)
            # 调用 设置目标抓拍时间参数 opt_begin = int(1-10)  第三个下拉框
            self.page_set_begin(opt_begin)
            # 调用 设置是否重复抓拍参数 re_radio=0/1;opt_re= int(1-10)  第四个下拉框
            self.page_set_recapture(re_radio, opt_re)
            # 调用 设置抓拍图片数参数 img_num = int 1-3
            self.page_set_images(img_num)
            # 调用 设置人脸外廓系数参数 sna_num = str(1.0-4.0)
            self.page_set_snapscale(sna_num)
            # 调用 设置抓拍最小人脸尺寸参数 size_num =int(32-256) 识别机最小参数为64
            self.page_set_snapsizethr(size_num)
            # 调用 点击确定
            self.page_click_accept()
        except Exception as e:
            allure.attach("失败描述", "IPC调参失败，原因：[{}]".format(e))
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("IPC调参失败")
            return False

    # 组合业务方法  -->升级IPC业务直接调用
    @allure.step(title="升级IPC操作")
    def upgrade_ipc(self, ota_version="first"):
        try:
            # 调用 点击升级按钮
            self.page_click_upgrade_btn()
            # 调用 点击OTA版本下拉框
            self.page_click_version_select()
            # 调用 选择版本下拉选项  ota_version =first/second
            self.page_sel_version_option(ota_version)
            # 调用 点击确定
            self.page_click_accept()
        except Exception as e:
            allure.attach("失败描述", "升级IPC失败，原因：[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("升级操作失败")
            return False

    # 组合业务方法  -->移除IPC业务直接调用
    @allure.step(title="移除IPC操作")
    def remove_ipc(self):
        try:
            # 调用 点击移除按钮
            self.page_click_remove_btn()
            # 调用 点击确定
            self.page_click_com_accept()
        except Exception as e:
            allure.attach("失败描述", "移除IPC失败，原因：[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("移除IPC失败")
            return False

    # 组合业务方法  -->搜索框业务直接调用 search_type=space_search/device_search
    @allure.step(title="搜索框操作")
    def input_search(self, search_type, search_text):
        try:
            if search_type == "space_search":
                # 调用 输入内容 -->空间搜索框
                self.page_click_space_search_input(search_text)
            elif search_type == "device_search":
                # 调用 输入内容 -->设备搜索框
                self.page_click_device_search_input(search_text)
            sleep(2)
        except Exception as e:
            allure.attach("失败描述", "搜索框操作失败，原因：[{}]".format(e))
            # 刷新
            self.refresh_current_page()
            # assert False
            raise Exception("搜索框操作失败")

    # 组合业务方法  -->下拉框业务直接调用 option_text =（"全部"/"HR-IPC22"/"HR-IPC2XX"）筒机/枪机
    @allure.step(title="下拉框选择操作")
    def select_ipc_type(self, option_text):
        try:
            # 调用 点击设备机型下拉框
            self.page_click_device_type_select()
            # 调用 选择下拉选项
            self.page_sel_type_option(option_text)
        except Exception as e:
            allure.attach("错误说明", "下拉框选择操作失败,原因:[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            raise Exception("下拉框选择失败")

    # 组合业务方法  -->编辑IPC位置业务直接调用
    @allure.step(title="编辑IPC位置")
    def edit_ipc_position(self, device_ip, position_text, device_type):
        try:
            # 调用 通过device_ip -->点击编辑ipc位置
            self.page_click_device_edit_position(device_ip, device_type)
            # 调用 编辑IPC位置弹框 -->输入位置信息
            self.page_enter_position(position_text)
            # 调用 点击确定
            self.page_click_accept()
        except Exception as e:
            allure.attach("失败说明", "编辑IPC位置操作失败,原因:[{}]".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # assert False
            # raise Exception("编辑IPC位置失败")
            return False

    # 组合业务方法  -->重启IPC业务直接调用
    @allure.step(title="重启IPC操作")
    def reboot_device(self, device_ip, device_type):
        try:
            # 调用 通过device_ip -->点击重启按钮
            self.page_click_device_reboot(device_ip, device_type)
            # 调用 点击确定
            self.page_click_com_accept()
        except Exception as e:
            allure.attach("错误说明", "重启IPC操作失败,原因:[{}]".format(e))
            # assert False
            # raise Exception("重启IPC失败")
            return False

    # 组合业务方法 -->调阈值业务直接调用 [客流与识别机使用]
    @allure.step(title="调阈值操作")
    def threshold_device(self, device_ip, device_type, threshold, tag):
        try:
            # 调用 通过device_ip -->点击设置按钮
            self.page_click_device_config(device_ip, device_type)
            if device_type == "客流识别机":
                # 清除线
                self.clear_line()
                # 调用 设置页面 -->开启识别功能开关
                self.page_open_recog()
            # 调用 设置页面 -->输入阈值
            self.config_threshold_ipc(threshold, tag)
        except:
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # raise Exception("调阈值失败")
            return False

    # 组合业务方法 -->画线业务直接调用 [客流使用]
    @allure.step(title="画线操作")
    def draw_line_device(self, device_ip, device_type, index=0, x1=998, y1=778, x2=334, y2=1000):
        try:
            # 调用 通过device_ip -->点击设置按钮
            self.page_click_device_config(device_ip, device_type)
            # 清除线
            self.clear_line()
            # 调用 设置页面 -->点击绘制线
            self.click_draw_lines_radio(index)
            # 调用 鼠标单击  画第一个点
            self.mouse_xy_click(x1, y1)
            # 调用 鼠标单击  画第二个点
            self.mouse_xy_click(x2, y2)
            # 调用 按键盘ESC键
            self.press_esc()
            # 调用 设置页面 -->点击保存
            self.page_config_click_save()
        except:
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # raise Exception("画线失败")
            return False

    # 组合业务方法 -->删除画线业务直接调用 [客流使用]
    @allure.step(title="删除画线操作")
    def del_draw_line_device(self, device_ip, device_type):
        try:
            # 调用 通过device_ip -->点击设置按钮
            self.page_click_device_config(device_ip, device_type)
            # 调用 清除线
            self.clear_line()
            # 调用 设置页面 -->点击保存
            self.page_config_click_save()
        except:
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # raise Exception("删除画线失败")
            return False

    # 组合业务方法 -->画线业务前置 [客流使用]
    @allure.step(title="清除线")
    def clear_line(self):
        try:
            while self.base_element_is_exist(Page.dev_del_line_btns):
                # 调用 设置页面 -->点击删除线
                self.click_del_line_btn()
        except:
            pass

    # 组合业务方法 -->画域业务前置 [抓拍/识别使用]
    @allure.step(title="清除域")
    def clear_area(self):
        if self.base_element_is_exist(Page.dev_del_area_btn):
            # 调用 设置页面 -->点击删除域线
            self.click_del_area_btn()

    # 组合业务方法 -->画域业务直接调用 识别/抓拍机使用]
    @allure.step(title="画域操作")
    def draw_area_device(self, device_ip, device_type, ):
        try:
            # 调用 通过device_ip -->点击设置按钮
            self.page_click_device_config(device_ip, device_type)
            # 清除域线
            self.clear_area()
            # 调用 设置页面 -->画域
            self.draw_area_line()
            # 调用 设置页面 -->点击保存
            self.page_config_click_save()
        except:
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # raise Exception("画域失败")
            return False

    # 组合业务方法 -->删除画线业务直接调用 [识别/抓拍机使用]
    @allure.step(title="删除画域操作")
    def del_draw_area_device(self, device_ip, device_type):
        try:
            # 调用 通过device_ip -->点击设置按钮
            self.page_click_device_config(device_ip, device_type)
            # 调用 设置页面 -->点击删除域线
            self.click_del_area_btn()
            # 调用 设置页面 -->点击保存
            self.page_config_click_save()
        except:
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            # raise Exception("删除画域失败")
            return False

    # 组合业务方法  -->清除空间业务直接调用,返回剩余空间数
    @allure.step(title="应用下大于5个空间时,清除其他空间")
    def clear_device_space_list(self):
        try:
            # 判断应用下设备空间数 > 5个
            if len(self.search_elements(Page.space_del_btns)) > 5:
                # 调用 刷新
                self.refresh_current_page()
                # 删除第一个应用下所有空的设备空间
                i = 0
                num = 0
                while i < 1:
                    # 查看应用下有多少个设备空间
                    all_del = len(self.search_elements(Page.space_del_btns))
                    sleep(2)
                    # 调用 通过index -->点击指定元素，从最后一个开始删除
                    self.index_click_element(Page.space_del_btns, all_del)
                    sleep(2)
                    if self.base_element_is_exist(Page.com_accept_btn):
                        # 调用 点击确定
                        self.page_click_com_accept()
                    elif self.base_element_is_exist(Page.com_know_btn):
                        # 调用 点击知道了
                        self.page_click_know()
                        num += 1
                    if num == all_del:
                        i += 1
                    sleep(2)
                    # 调用 刷新
                    self.refresh_current_page()
                sleep(1)
                return num
        except Exception as e:
            allure.attach("错误说明", "清除失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            # assert False
            raise Exception("清除多余设备空间失败")

    # 组合业务方法  -->设备列表取出设备IP【设备接入paas断言使用】
    @allure.step(title="设备列表取出设备iP")
    def device_list_get_ip(self, device_type, space_name, device_ip):
        try:
            # 调用 通过文本点击元素 -->点击设备空间
            self.text_click_element(space_name)
            # 调用 通过文本点击元素 -->点击设备类型
            self.text_click_element(device_type)
            sleep(3)
            # 调用 通过文本定位单个元素 -->返回页面设备IP值
            page_device_ip = self.text_search_element(device_ip).text
            allure.attach("描述", "页面取出设备IP:[{}]".format(page_device_ip))
            allure.attach("描述", "页面取出设备IP:[%s]在设备列表中" % (page_device_ip))
            return page_device_ip
        except Exception as e:
            allure.attach("失败说明", "%s不在设备列表中,原因%s" % (device_ip, e))
            return None

    # 组合业务方法  -->确保前三个设备空间名为：Guo_Flow/Guo_Snap/Guo_Recog【空间相关脚本使用】
    @allure.step(title="确保前三个设备空间名为：Guo_Flow/Guo_Snap/Guo_Recog")
    def sure_point_name_info(self):
        try:
            # 空间数>=3时，判断Guo相关名称是否存在
            if len(self.search_elements(Page.space_del_btns)) >= 3:
                if (self.search_elements(Page.space_names)[1].text == "Guo_Flow") and \
                        (self.search_elements(Page.space_names)[2].text == "Guo_Snap") and \
                        (self.search_elements(Page.space_names)[3].text == "Guo_Recog"):
                    pass
            else:
                sleep(3)
                # 获取所有空间名
                space_names = self.search_elements(Page.space_names)
                if len(space_names) > 4:
                    pass
                elif len(space_names) == 3:
                    # 调用 添加设备空间
                    self.add_device_space("my_name")
                elif len(space_names) == 2:
                    # 调用 添加设备空间
                    self.add_device_space("my_name1")
                    self.add_device_space("my_name2")
                elif len(space_names) == 1:
                    # 调用 添加设备空间
                    self.add_device_space("my_name1")
                    self.add_device_space("my_name2")
                    self.add_device_space("my_name3")
                i = 1
                while i < len(self.search_elements(Page.space_names)):
                    # 调用 通过index -->点击指定元素 修改按钮
                    self.index_click_element(Page.space_edit_btns, i)
                    # 修改空间名为 guo_X
                    self.send_element(Page.space_name_input, "guo_{}".format(i))
                    # 调用 点击确定
                    self.page_click_accept()
                    i += 1
                sleep(3)
                a = 1
                # 循环修改前三个空间名为 Guo_Flow/Guo_Snap/Guo_Recog
                while a < len(self.search_elements(Page.space_names)):
                    self.index_click_element(Page.space_edit_btns, a)
                    if a == 1:
                        self.send_element(Page.space_name_input, "Guo_Flow")
                    if a == 2:
                        self.send_element(Page.space_name_input, "Guo_Snap")
                    if a == 3:
                        self.send_element(Page.space_name_input, "Guo_Recog")
                    sleep(2)
                    # 调用 点击确定
                    self.page_click_accept()
                    a += 1
        except Exception as e:
            allure.attach("错误说明", "确保前三个设备空间名失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            # assert False
            raise Exception("确保前三个设备空间名失败")

    # 组合业务方法 -->选择设备【设备相关脚本使用】
    # @allure.step(title="选择设备")
    def preposition_device(self, device_type, device_ip, space_name=a.space_name):
        try:
            # 调用 通过文本点击元素 -->点击设备空间tab
            self.text_click_element(space_name)
            # 调用 通过文本点击元素 -->点击设备机型tab (客流/抓拍/识别)
            if device_type != None:
                self.text_click_element(device_type)
            # 调用 点击设备前的复选框
            if device_type != None:
                self.page_click_ip_checkbox(device_ip)
        except Exception as e:
            allure.attach("错误说明", "选择设备失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            # 刷新页面
            self.refresh_current_page()
            return False
            # assert False
            # raise Exception("选择设备失败")

    # ----------------------------------------------------[断言]test脚本使用-------------------------------------------------

    # 断言 -->判断设备空间是否在应用下【设备空间断言使用】True/False
    @allure.step(title="断言设备空间在应用下")
    def if_new_space_name_exits(self, space_name):
        try:
            # 调用 获取第一个应用下所有设备空间名
            space_names = self.page_get_space_names()
            names = []
            for i in space_names:
                names.append(i.text)
            allure.attach("第一个应用下所有设备空间:{}".format(names))
            if len(space_name) > 20:
                space_name = space_name[:20]
            # 调用 断言 -->keyword in expect结果
            return self.base_if_include(space_name, names)
        except Exception as e:
            allure.attach("失败描述", "判断失败，原因：{}".format(e))
            # 截图
            self.screen_page()
            # 刷新
            self.refresh_current_page()
            assert False

    # 断言 -->判断toast消息，toast=add/edit【设备空间断言使用】 True/False
    @allure.step(title="断言页面提示toast消息 == 预期toast消息")
    def if_toast_equal_expect(self, toast_text, toast):
        try:
            if toast == "add":
                # 调用 断言 -->actual结果 == expect结果
                return self.base_if_equal(toast_text, "添加成功！")
            elif toast == "edit":
                # 调用 断言 -->actual结果 == expect结果
                return self.base_if_equal(toast_text, "修改成功！")
        except Exception:
            allure.attach("失败说明", "页面提示toast != 预期")
            assert False

    # 断言 -->页面所有参数 == 配置所有参数【调参断言使用】True/False
    @allure.step(title="断言页面所有参数 == 配置所有参数")
    def if_param_page_equal(self, opt_fro, opt_track, opt_begin,
                            opt_re, img_num, sna_num, size_num, device_ip,
                            re_radio):
        """
        :param opt_track: 灵敏度(1-10)
        :param opt_begin: 目标抓拍时间(1-10)
        :param opt_re: 再次抓取时间差(1-10) 客流机无此参数给None
        :param img_num: 抓拍图片数(1-3) 客流机与识别机无此参数给None
        :param sna_num: 人脸外廓系数(1.0-4.0)
        :param size_num: 抓拍最小人脸尺寸(32-256) 识别机最小参数为64
        :param re_radio:  是否开启重复抓拍：0为关闭，1为开启 客流机无此参数
        :param opt_fro: 抓拍阈值(21-30)
        :param device_ip: 设备IP
        :return: True/False
        """
        try:
            # 调用 获取页面所有参数
            page_param = self.page_get_page_prarms(device_ip)
            # 调用 转换配置所有参数
            param = self.page_trans_set_params(opt_fro, opt_track, opt_begin,
                                               opt_re, img_num, sna_num, size_num,
                                               re_radio)
            sleep(2)
            # 对比两组数据
            num = 0
            for i in range(0, len(page_param)):
                if param[i] == None:
                    num += 1
                    pass
                if page_param[i] == "":
                    pass
                    num += 1
                elif str(param[i]) == str(page_param[i]):
                    num += 1
            sleep(2)
            if num >= len(page_param):
                allure.attach("描述", "页面所有参数 == 配置所有参数")
                allure.attach("描述", "对比相等参数为:[{}]个".format(num))
                allure.attach("描述", "对比相等参数为:[{}]个".format(num))
                return True
            else:
                allure.attach("描述", "页面所有参数 != 配置所有参数")
                return False
        except Exception as e:
            allure.attach("失败描述", "断言页面参数与配置参数失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            assert False
        finally:
            sleep(3)
            # 关闭调参弹框
            self.close_message_box()

    # 断言 -->telnet所有参数 == 配置所有参数【调参断言使用】True/False
    @allure.step(title="断言telnet所有参数 == 配置所有参数")
    def if_param_telnet_equal(self, opt_fro, opt_track, opt_begin,
                              opt_re, img_num, sna_num, size_num, device_ip,
                              re_radio):
        """
        :param opt_track: 灵敏度(1-10)
        :param opt_begin: 目标抓拍时间(1-10)
        :param opt_re: 再次抓取时间差(1-10) 客流机无此参数给None
        :param img_num: 抓拍图片数(1-3) 客流机与识别机无此参数给5
        :param sna_num: 人脸外廓系数(1.0-4.0)
        :param size_num: 抓拍最小人脸尺寸(32-256) 识别机最小参数为64
        :param re_radio:  是否开启重复抓拍：0为关闭，1为开启 客流机无此参数
        :param device_ip: 设备IP
        :return: True/False
        """
        try:
            # 调用 获取telnet所有参数
            telnet_param = TelnetClient().telnet_ipc_param(device_ip)
            # 调用 转换配置所有参数
            param = self.page_trans_set_params(opt_fro, opt_track, opt_begin,
                                               opt_re, img_num, sna_num, size_num,
                                               re_radio)
            sleep(2)
            # 对比两组数据
            num = 0
            for i in range(0, len(param)):
                if param[i] == None:
                    num += 1
                    pass
                elif str(param[i]) == str(telnet_param[i]):
                    num += 1
            sleep(2)
            if num >= len(param):
                allure.attach("描述", "telnet所有参数 == 配置所有参数")
                allure.attach("描述", "对比相等参数为:[{}]个".format(num))
                allure.attach("描述", "需对比参数共:[{}]个".format(len(param)))
                return True
            else:
                allure.attach("描述", "telnet所有参数 != 配置所有参数")
                return False
        except Exception as e:
            allure.attach("失败描述", "断言telnet参数与配置参数失败,原因:{}".format(e))
            assert False

    # 断言 -->判断页面OTA版本 == 配置OTA版本 【单个设备升级断言使用】True/False
    @allure.step(title="断言页面OTA版本 == 配置OTA版本")
    def if_get_page_ota(self, device_ip, version, device_type):
        try:
            # 调用 通过space_name文本点击元素 -->点击设备空间tab
            self.text_click_element(a.space_name)
            # 调用 通过device_ip -->返回设备ota版本值
            ota_version = self.page_get_device_ota(device_ip, device_type)
            allure.attach("页面此设备状态信息", "此设备OTA版本：{}".format(ota_version))
            # 调用 断言 -->actual结果 == expect结果
            return self.base_if_equal(ota_version, version)
        except Exception as e:
            allure.attach("失败描述", "断言页面与配置OTA版本失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            assert False

    # 断言 -->查看页面OTA版本 == 配置OTA版本 【移动IPC断言使用】True/False
    @allure.step(title="断言设备在移动后的设备空间")
    def if_ipc_move_space(self, device_type, device_ip, space_name):
        try:
            # 调用 通过space_name文本点击元素 -->点击设备空间tab
            self.text_click_element(space_name)
            # 调用 通过文本点击元素 -->点击设备类型tab  客流/抓拍/识别
            self.text_click_element(device_type)
            # 判断此设备device_ip是否在设备空间下
            if self.text_search_element(device_ip):
                allure.attach("描述", "设备:{}在设备空间:{}"
                              .format(device_ip, space_name))
                return True
            else:
                allure.attach("描述", "设备:{}不在设备空间:{}"
                              .format(device_ip, space_name))
                return False
        except Exception as e:
            allure.attach("失败描述", "断言设备在设备空间下失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            assert False

    # 断言 -->telnet中space_id == 页面space_id  【移动/移除IPC断言使用】True/False
    @allure.step(title="断言telnet中space_id == 页面space_id")
    def if_ipc_move_space_telnet(self, device_ip):
        try:
            # 调用 获取页面space_id  移动后的设备空间
            page_space_id = self.page_get_move_page_space_id()
            # 调用 通设备IP -->获取telnet中space_id
            telnet_space_id = TelnetClient().telnet_ipc_space(device_ip)
            # 调用 断言 -->actual结果 == expect结果
            return self.base_if_equal(telnet_space_id, page_space_id)
        except Exception as e:
            allure.attach("失败描述", "断言telnet中与页面space_id失败,原因:{}".format(e))
            assert False

    @allure.step(title="获取设备状态")
    def get_status(self, device_type, device_ip):
        sleep(1)
        # 调用 通过device_ip -->返回设备状态值
        status = self.page_get_device_status(device_ip, device_type)
        allure.attach("描述", "设备：{}的操作状态为：{}".format(device_type, status))
        return status

    # 断言 -->设备两个操作状态为成功  【画线/调参断言使用】True/False
    @allure.step(title="断言设备第一个操作状态 == 成功")
    def if_two_seuss_status(self, device_type, device_ip):
        try:
            sleep(1)
            # 调用 通过文本点击元素 -->点击设备类型tab 客流/抓拍/识别
            # self.text_click_element(device_type)
            # sleep(5)
            # 调用 通过device_ip -->返回设备状态值
            status = self.page_get_device_status(device_ip, device_type)
            allure.attach("描述", "设备：{}的操作状态为：{}".format(device_type, status))
            # 调用 通过device_ip -->点击设备状态详细信息
            self.page_click_device_status(device_ip, device_type)
            sleep(1)
            # 调用 定位一组元素 -->获取详情页，第一个操作的所有信息文本
            first_status = self.search_elements(Page.dev_first_status_text)
            sleep(1)
            device_operation_text = []
            for i in range(0, len(first_status)):
                print(i)
                if i == 0:
                    allure.attach("描述", "当前操作为：[{}]".format(first_status[i].text))
                sleep(1)
                if i == 1:
                    # 添加状态
                    device_operation_text.append(first_status[i].text)
                sleep(1)
                if i == 2:
                    # 添加操作时间
                    print("时间：", first_status[i].text)
                    device_operation_text.append(first_status[i].text)
            allure.attach("描述", "设备详细信息的状态:[{}]".format(device_operation_text[0]))
            allure.attach("描述", "设备详细信息的时间:[{}]".format(device_operation_text[1]))
            # 调用 定位一组元素 -->获取详情页，第二个操作的所有信息文本
            second_status = self.search_elements(Page.dev_second_status_text)
            sleep(1)
            device_second_text = []
            for i in range(0, len(second_status)):
                print(i)
                if i == 0:
                    allure.attach("描述", "当前操作为：[{}]".format(second_status[i].text))
                sleep(1)
                if i == 1:
                    # 添加状态
                    device_second_text.append(second_status[i].text)
                sleep(1)
                if i == 2:
                    # 添加操作时间
                    print("时间：", second_status[i].text)
                    device_second_text.append(second_status[i].text)
            allure.attach("描述", "设备详细信息的状态:[{}]".format(device_second_text[0]))
            allure.attach("描述", "设备详细信息的时间:[{}]".format(device_second_text[1]))
            # 判断是否为成功
            if device_operation_text[0] == device_second_text[0] == status == "成功":
                sleep(1)
                allure.attach("状态详细信息", "当前操作成功")
                return True
            elif device_operation_text[0] == device_second_text[0] == "成功":
                sleep(1)
                allure.attach("状态详细信息", "当前操作成功")
                return True
            else:
                sleep(1)
                allure.attach("失败描述", "设备:[{}]当前操作失败".format(device_ip))
                # 截图
                self.screen_page()
                return False
        except Exception as e:
            allure.attach("失败描述", "断言设备操作状态失败,原因:{}".format(e))
            # 截图
            self.screen_page()
            assert False

    # 断言 -->搜索内容search_text在页面中  【设备搜索框断言使用】True/False
    @allure.step(title="断言搜索内容是否在页面结果中")
    def if_device_search_text_in(self, search_text):
        try:
            # 调用 获取页面设备信息
            all_text = self.page_get_device_text(search_text)[0]
            if all_text == 0:
                return True
            else:
                for i in all_text:
                    # 调用 断言 -->keyword in expect结果
                    return self.base_if_include(search_text, i)
        except Exception as e:
            allure.attach("失败描述", "断言搜索内容是否在页面结果中失败,原因:{}".format(e))
            assert False

    # 断言 -->name在页面结果中 【空间搜索框断言使用】 True/False
    @allure.step(title="断言name在页面结果中")
    def if_space_search_text_in(self, search_text):
        try:
            # 调用 获取设备空间栏所有app_name+space_name
            all_text = self.page_get_names()
            # 判断search内容是否在其中
            for i in all_text:
                if (search_text in i) or (search_text == i):
                    allure.attach("判断描述", "搜索内容：{}在设备空间栏".format(search_text))
                    return True
            sleep(2)
        except Exception as e:
            allure.attach("判断描述", "搜索内容：{}不在设备空间栏,原因：{}"
                          .format(search_text, e))
            assert False

    # 断言 -->搜索出所有结果 == 选择机型search_text 【设备筛选框断言使用】True/False
    @allure.step(title="断言搜索出所有结果 == 选择机型")
    def if_select_equal_page(self, search_text):
        try:
            # 调用 获取页面设备信息
            all_text = self.page_get_device_text(search_text)[0]
            x = 0
            for i in all_text:
                if len(i) < 20:
                    pass
                elif search_text in i:
                    x += 1
            # 调用 断言 -->actual结果 == expect结果
            return self.base_if_equal(x, len(all_text))
        except Exception as e:
            allure.attach("错误说明", "判断搜索所有结果失败,原因:{}".format(e))
            assert False

    # 断言 -->页面显示位置 == 修改信息值position_text 【编辑IPC位置断言使用】 True/False
    @allure.step(title="断言页面显示位置 == 修改信息值")
    def if_ipc_position_equal(self, device_ip, position_text, device_type):
        try:
            # 调用 通过device_ip -->返回设备位置信息值
            page_position = self.page_get_device_position(device_ip, device_type)
            # 断言页面显示位置 == 修改信息值
            if len(position_text) > 10:
                position_text = position_text[:10]
            # 调用 断言 -->actual结果 == expect结果
            return self.base_if_equal(page_position, position_text)
        except Exception as e:
            allure.attach("错误说明", "断言页面显示位置 == 修改信息值失败,原因:{}".format(e))
            assert False

    # 断言 -->设备在线 【重启/设备接入断言使用】 True/False
    @allure.step(title="断言设备在线")
    def if_device_online(self, device_ip):
        try:
            # 调用 通过device_ip -->返回设备在线状态值
            online_status_text = self.page_get_device_online_status(device_ip)
            # 调用 断言 -->actual结果 == expect结果
            return self.base_if_equal(online_status_text, "在线")
        except Exception as e:
            allure.attach("错误说明", "断言设备在线状态操作失败,原因:{}".format(e))
            assert False

    # 断言配置阈值 == 查询阈值
    @allure.step(title="断言配置阈值 == 查询阈值")
    def if_threshold_equal(self, api_t, tag, threshold):
        try:
            for i in range(0, len(api_t)):
                if api_t[0] == int(threshold):
                    if tag == 1:
                        allure.attach("描述", "修改第一个阈值，断言配置阈值 == 查询阈值")
                        return True
                else:
                    assert False
                if tag == 2:
                    if api_t[1] == int(threshold):
                        allure.attach("描述", "修改两个阈值，断言配置阈值 == 查询阈值")
                        return True
                    else:
                        assert False
        except Exception as e:
            allure.attach("错误说明", "断言配置阈值 != 查询阈值失败,原因:{}".format(e))
            assert False


if __name__ == '__main__':
    p = PageDevice(get_driver())
    # 固定使用 创建人脸库
    # p.api_create_faces()
    # 固定使用 绑定人脸库
    # p.api_bind_faces("068B3001010110158L", Page.faceset_id_01)
    sleep(10)
    # p.api_bind_faces("068B3001010110158L", Page.faceset_id_02)

    # 登录
    p.send_element(Page.login_email_id, Page.test_user)
    p.send_element(Page.login_password_id, Page.test_pwd)
    p.click_element(Page.login_btn_id)
    # 进入设备列表
    p.click_element(Page.gps_device_man_btn)
    p.click_element(Page.gps_dev_list_btn)

    # 测试 选择设备
    p.preposition_device("Guo_Recog", "识别机", "10.64.31.47")
    # 测试 移动设备
    # p.move_ipc("Guo_Flow")
    # 调参 客流识别机
    # p.param_ipc(2, 5, 2, None, "2.1", 221, 6)
    # 抓拍
    p.param_ipc(1, 1, 1, 1, 1, "2.1", 221, 0)
    # 测试 调阈值
    # p.threshold_device("10.64.31.58", "识别机", "55", 1)
    # 查询人脸库阈值
    # p.api_search_faces(Page.faceset_id_02,'10.64.31.59')
    # 页面获取阈值
    # p.page_get_threshold_input("10.64.31.47", "识别机")
